package com.linkhub.oms.admin.modules.pickuporder.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.github.yulichang.wrapper.resultmap.MFunc;
import com.github.yulichang.wrapper.resultmap.MybatisLabelFree;
import com.google.common.collect.Lists;
import com.linkhub.oms.admin.common.exception.ExceptionFactory;
import com.linkhub.oms.admin.modules.order.service.OrderBizService;
import com.linkhub.oms.admin.modules.pickuporder.constant.PickUpOrderConstant;
import com.linkhub.oms.admin.modules.pickuporder.domain.dto.EntryOrderLineExcelDTO;
import com.linkhub.oms.admin.modules.pickuporder.domain.param.EntryOrderStateChangeParam;
import com.linkhub.oms.admin.modules.pickuporder.domain.param.MarkCompletionParam;
import com.linkhub.oms.admin.modules.pickuporder.domain.param.PickUpOrderQueryParam;
import com.linkhub.oms.admin.modules.pickuporder.domain.param.PickUpOrderSaveOrUpdateParam;
import com.linkhub.oms.admin.modules.pickuporder.domain.vo.EntryOrderLineImportResultVO;
import com.linkhub.oms.admin.modules.pickuporder.domain.vo.EntryOrderResultVO;
import com.linkhub.oms.admin.modules.pickuporder.domain.vo.PickUpOrderDetailVO;
import com.linkhub.oms.admin.modules.pickuporder.domain.vo.PickUpOrderVO;
import com.linkhub.oms.admin.modules.pickuporder.listener.EntryOrderLineListener;
import com.linkhub.oms.admin.modules.pickuporder.service.PickUpOrderBizService;
import com.linkhub.oms.admin.modules.pickuporder.util.PickUpOrderAssist;
import com.linkhub.oms.admin.modules.stock.domain.dto.PassageStockDTO;
import com.linkhub.oms.admin.modules.stock.service.StockBizService;
import com.linkhub.oms.admin.modules.stock.service.StockHandler;
import com.linkhub.oms.admin.modules.satoken.session.LhSessionContext;
import com.linkhub.oms.admin.modules.stock.domain.dto.PassageStockDTO;
import com.linkhub.oms.admin.modules.stock.service.StockBizService;
import com.linkhub.oms.admin.modules.user.account.domain.dto.UserAccountDTO;
import com.linkhub.oms.admin.modules.user.account.service.IUserAccountService;
import com.linkhub.oms.admin.modules.user.accountflow.domain.dto.UserAccountFlowDTO;
import com.linkhub.oms.admin.modules.user.accountflow.service.IUserAccountFlowBizService;
import com.linkhub.oms.common.constant.WmsInfoConstant;
import com.linkhub.oms.common.enums.IEnumConvert;
import com.linkhub.oms.common.enums.mp.*;
import com.linkhub.oms.common.response.PageDTO;
import com.linkhub.oms.common.util.CacheKeyAssist;
import com.linkhub.oms.common.util.QtBeanUtil;
import com.linkhub.oms.common.util.QtStreamUtil;
import com.linkhub.oms.common.util.WmsUtil;
import com.linkhub.oms.component.excel.util.EasyExcelUtil;
import com.linkhub.oms.component.mp.util.QtMybatisPlusUtil;
import com.linkhub.oms.component.redis.locker.DistributedLocker;
import com.linkhub.oms.dao.mapper.PickUpGoodsOrderEntityMapper;
import com.linkhub.oms.dao.mpservice.IEntryOrderLineService;
import com.linkhub.oms.dao.mpservice.IEntryOrderResultService;
import com.linkhub.oms.dao.mpservice.ILocalProductSupplierService;
import com.linkhub.oms.dao.mpservice.IPickUpGoodsOrderService;
import com.linkhub.oms.dao.mpservice.ISupplierService;
import com.linkhub.oms.data.sync.api.wms.domain.dto.WmsEntryOrderBatchCreateDTO;
import com.linkhub.oms.data.sync.api.wms.domain.response.EntryOrderBatchCreateResponse;
import com.linkhub.oms.data.sync.service.WMSApiService;
import com.linkhub.oms.entity.EntryOrderLineEntity;
import com.linkhub.oms.entity.LocalProductEntity;
import com.linkhub.oms.entity.PickUpGoodsOrderEntity;
import com.linkhub.oms.entity.UserEntity;
import com.linkhub.oms.entity.resulttype.entryorder.EntryOrderLineResultEntity;
import com.linkhub.oms.entity.resulttype.entryorder.EntryOrderResultMapEntity;
import com.linkhub.oms.entity.resulttype.stock.ProductStockResultEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.linkhub.oms.admin.modules.pickuporder.constant.PickUpOrderConstant.ENTRY_ORDER_LINE_TEMPLATE_NAME;

/**
 * @Description: PickUpOrderBizService
 * @Author: echo
 * @Date: 2024/5/2 19:27
 * @Version: 1.0
 */
@Slf4j
@Service
public class PickUpOrderBizServiceImpl implements PickUpOrderBizService {
    @Resource
    private IPickUpGoodsOrderService pickUpGoodsOrderService;
    @Resource
    private IEntryOrderLineService entryOrderLineService;
    @Resource
    private PickUpGoodsOrderEntityMapper pickUpGoodsOrderEntityMapper;
    @Resource
    private ISupplierService supplierService;
    @Resource
    private OrderBizService orderBizService;
    @Resource
    private IEntryOrderResultService entryOrderResultService;
    @Resource
    private ILocalProductSupplierService localProductSupplierService;
    @Resource
    private DistributedLocker distributedLocker;
    @Resource
    private StockBizService stockBizService;
    @Resource
    private WMSApiService wmsApiService;
    @Resource
    private IUserAccountService userAccountService;
    @Resource
    private IUserAccountFlowBizService userAccountFlowService;
    @Resource
    private StockHandler stockHandler;

    @Override
    public PageDTO<PickUpOrderVO> pageOrders(PickUpOrderQueryParam orderQueryParam) {
        MPJLambdaWrapper<PickUpGoodsOrderEntity> queryWrapper = createEntryOrderListWrapper(orderQueryParam);
        Page<PickUpGoodsOrderEntity> objectPage = new Page<>(orderQueryParam.getPage(), orderQueryParam.getSize());
        objectPage.setOptimizeJoinOfCountSql(false);

        Page<PickUpGoodsOrderEntity> page = pickUpGoodsOrderEntityMapper.selectJoinPage(objectPage,
                PickUpGoodsOrderEntity.class,
                queryWrapper);

        return QtMybatisPlusUtil.convertPage(page, PickUpOrderVO::convert);
    }

    @Override
    public PickUpOrderDetailVO getOrderDetail(String sysEntryOrderCode, boolean customerRole) {
        MPJLambdaWrapper<PickUpGoodsOrderEntity> wrapper = createEntryOrderDetailWrapper(sysEntryOrderCode);
        PickUpGoodsOrderEntity pickUpGoodsOrderEntity = pickUpGoodsOrderEntityMapper.selectJoinOne(PickUpGoodsOrderEntity.class, wrapper);
        PickUpOrderDetailVO vo = PickUpOrderDetailVO.convert(pickUpGoodsOrderEntity);
        if (customerRole) {
            vo.setRealTakeDeliveryCost(null);
        }

        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addPickUpOrder(PickUpOrderSaveOrUpdateParam saveParam) {

        // 系统供应商id 校验
        String sysSupplierId = saveParam.getSysSupplierId();
        if (!supplierService.exist(saveParam.getUserId(), sysSupplierId)) {
            throw ExceptionFactory.getI18nBizException("supplier.sysSupplierId.error");
        }
        PickUpGoodsOrderEntity saveEntity = PickUpOrderAssist.createSaveEntity(saveParam);
        orderBizService.saveEntryOrders(saveEntity);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @SuppressWarnings("all")
    public void editPickUpOrder(PickUpOrderSaveOrUpdateParam editParam) {
        boolean isCustomerRole = editParam.isCustomerRole();

        if (!isCustomerRole) {
            if (StringUtils.isBlank(editParam.getPredictArrivalTime())) {
                throw ExceptionFactory.getI18nBizException("validation.pick.up.predictArrivalTime.notNull");
            }
        }

        String sysEntryOrderCode = editParam.getSysEntryOrderCode();
        // 查询数据
        PickUpGoodsOrderEntity pickUpGoodsOrder = pickUpGoodsOrderService.queryBySysEntryOrderCode(sysEntryOrderCode);
        if (Objects.isNull(pickUpGoodsOrder)) {
            throw ExceptionFactory.getI18nBizException("pick.up.order.sysEntryOrderCode.error");
        }

        // 校验提货状态是否可编辑
        if (!PickUpOrderConstant.COULD_EDIT_STATUS_LIST.contains(pickUpGoodsOrder.getState())) {
            throw ExceptionFactory.getI18nBizException("pick.up.order.edit.state.error");
        }

        String entryOrderEditLockKey = CacheKeyAssist.getEntryOrderEditLockKey(sysEntryOrderCode);
        try {

            if (!distributedLocker.tryLock(entryOrderEditLockKey)) {
                throw ExceptionFactory.getI18nBizException("pick.up.order.concurrence.error");
            }

            editParam.resetField();
            if (isCustomerRole) {
                // 系统供应商id 校验
                String sysSupplierId = editParam.getSysSupplierId();
                if (!supplierService.exist(editParam.getUserId(), sysSupplierId)) {
                    throw ExceptionFactory.getI18nBizException("supplier.sysSupplierId.error");
                }
            }

            PickUpGoodsOrderEntity updateEntity = PickUpOrderAssist.createUpdateEntity(editParam);
            updateEntity.setId(pickUpGoodsOrder.getId());

            orderBizService.updateEntryOrders(updateEntity);
        } finally {
            distributedLocker.unlock(entryOrderEditLockKey);
        }
    }

    @Override
    public List<EntryOrderResultVO> getEntryOrderResult(String sysEntryOrderCode) {
        List<EntryOrderResultMapEntity> orderResultList = entryOrderResultService.queryEntryOrderResults(sysEntryOrderCode);
        return QtBeanUtil.copyList(orderResultList, EntryOrderResultVO::new);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancel(String sysEntryOrderCode) {
        // 查询数据
        PickUpGoodsOrderEntity pickUpGoodsOrder = pickUpGoodsOrderService.queryBySysEntryOrderCode(sysEntryOrderCode);
        if (Objects.isNull(pickUpGoodsOrder)) {
            throw ExceptionFactory.getI18nBizException("pick.up.order.sysEntryOrderCode.error");
        }

        // 校验提货状态
        if (!Objects.equals(pickUpGoodsOrder.getState(), PickUpOrderStatusEnum.PENDING_CHECK)) {
            throw ExceptionFactory.getI18nBizException("pick.up.order.cancel.state.error");
        }

        String entryOrderEditLockKey = CacheKeyAssist.getEntryOrderEditLockKey(sysEntryOrderCode);
        try {
            if (!distributedLocker.tryLock(entryOrderEditLockKey)) {
                throw ExceptionFactory.getI18nBizException("pick.up.order.concurrence.error");
            }
            pickUpGoodsOrderService.cancel(sysEntryOrderCode);
        } finally {
            distributedLocker.unlock(entryOrderEditLockKey);
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeState(EntryOrderStateChangeParam stateChangeParam) {
        Integer curStatus = stateChangeParam.getCurStatus();
        Integer changeStatus = stateChangeParam.getChangeStatus();
        if (changeStatus <= curStatus) {
            throw ExceptionFactory.getI18nBizException("pick.up.order.change.state.error");
        }
        String sysEntryOrderCode = stateChangeParam.getSysEntryOrderCode();
        PickUpGoodsOrderEntity entryOrder = pickUpGoodsOrderService.queryBySysEntryOrderCode(sysEntryOrderCode);
        List<EntryOrderLineEntity> entryOrderLines = entryOrderLineService.listEntryOrderLines(sysEntryOrderCode);
        if (Objects.isNull(entryOrder) || CollUtil.isEmpty(entryOrderLines)) {
            throw ExceptionFactory.getI18nBizException("pick.up.order.sysEntryOrderCode.error");
        }


        String entryOrderEditLockKey = CacheKeyAssist.getEntryOrderEditLockKey(sysEntryOrderCode);
        try {
            if (!distributedLocker.tryLock(entryOrderEditLockKey)) {
                throw ExceptionFactory.getI18nBizException("pick.up.order.concurrence.error");
            }
            // 状态变更
            PickUpOrderStatusEnum beforeState = IEnumConvert.valueOf(curStatus, PickUpOrderStatusEnum.class);
            PickUpOrderStatusEnum state = IEnumConvert.valueOf(changeStatus, PickUpOrderStatusEnum.class);
            pickUpGoodsOrderService.changeState(sysEntryOrderCode, beforeState, state);

            if ((Objects.equals(PickUpOrderStatusEnum.IN_PRODUCTION, state)
                    || Objects.equals(PickUpOrderStatusEnum.IN_TRANSIT, state)) 
                    && Objects.equals(PickUpOrderStatusEnum.PENDING_CHECK, beforeState)) {
                // 状态变为生产中，则需要创建入库单，且生产在途流水
                WmsEntryOrderBatchCreateDTO wmsEntryOrderBatchCreateDTO = new WmsEntryOrderBatchCreateDTO();
                wmsEntryOrderBatchCreateDTO.setEntryOrderCode(entryOrder.getSysEntryOrderCode());
                wmsEntryOrderBatchCreateDTO.setOwnerCode(WmsInfoConstant.OWNER_CODE);
                wmsEntryOrderBatchCreateDTO.setWarehouseCode(WmsInfoConstant.WAREHOUSE_CODE);
                wmsEntryOrderBatchCreateDTO.setOrderType("CGRK");
                wmsEntryOrderBatchCreateDTO.setExpectStartTime(DateUtil.format(entryOrder.getPredictArrivalTime(),
                        DatePattern.UTC_SIMPLE_PATTERN));
                wmsEntryOrderBatchCreateDTO.setLogisticsName(entryOrder.getLogisticsCompany());
                wmsEntryOrderBatchCreateDTO.setExpressCode(entryOrder.getLogisticsOddNumber());
                wmsEntryOrderBatchCreateDTO.setSupplierCode(entryOrder.getSysSupplierId());
                wmsEntryOrderBatchCreateDTO.setUserDefined1(entryOrder.getUserId());
                List<WmsEntryOrderBatchCreateDTO.ProductParam> products = Lists.newArrayList();
                for (EntryOrderLineEntity entryOrderLine : entryOrderLines) {
                    WmsEntryOrderBatchCreateDTO.ProductParam product = new WmsEntryOrderBatchCreateDTO.ProductParam();
                    product.setItemCode(WmsUtil.createItemCode(entryOrder.getUserId(), entryOrderLine.getSkuId()));
                    product.setPlanQty(String.valueOf(entryOrderLine.getSkuQuantity()));
                    products.add(product);
                }
                wmsEntryOrderBatchCreateDTO.setProductInfo(products);
                wmsEntryOrderBatchCreateDTO.setOutBizCode(entryOrder.getSysEntryOrderCode());
                EntryOrderBatchCreateResponse response = wmsApiService.batchCreateEntryOrder(wmsEntryOrderBatchCreateDTO);
                if (!response.success()) {
                    throw ExceptionFactory.getI18nBizException("pick.up.order.batch.create.error");
                }
                if (response.success()) {
                    // 库存模块对入库单创建的处理
                    stockHandler.wmsInboundCreated(wmsEntryOrderBatchCreateDTO);
                }
            }

        } finally {
            distributedLocker.unlock(entryOrderEditLockKey);
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void markComplete(MarkCompletionParam markCompletionParam) {
        String sysEntryOrderCode = markCompletionParam.getSysEntryOrderCode();
        PickUpGoodsOrderEntity pickUpGoodsOrder = pickUpGoodsOrderService.queryBySysEntryOrderCode(sysEntryOrderCode);
        if (Objects.isNull(pickUpGoodsOrder)) {
            throw ExceptionFactory.getI18nBizException("pick.up.order.sysEntryOrderCode.error");
        }

        if (!Objects.equals(pickUpGoodsOrder.getState(), PickUpOrderStatusEnum.BE_IN_STORAGE)) {
            throw ExceptionFactory.getI18nBizException("pick.up.order.mark.state.error");
        }
        String entryOrderEditLockKey = CacheKeyAssist.getEntryOrderEditLockKey(sysEntryOrderCode);

        try {
            if (!distributedLocker.tryLock(entryOrderEditLockKey)) {
                throw ExceptionFactory.getI18nBizException("pick.up.order.concurrence.error");
            }
            PickUpGoodsOrderEntity updateEntity = new PickUpGoodsOrderEntity();
            updateEntity.setId(pickUpGoodsOrder.getId());
            String takeDeliveryCost = markCompletionParam.getTakeDeliveryCost();
            updateEntity.setTakeDeliveryCost(takeDeliveryCost);
            updateEntity.setRealTakeDeliveryCost(markCompletionParam.getRealTakeDeliveryCost());
            updateEntity.setState(PickUpOrderStatusEnum.FINISHED);
            pickUpGoodsOrderService.updateById(updateEntity);
            String userId = pickUpGoodsOrder.getUserId();
            BigDecimal cost = NumberUtil.toBigDecimal(takeDeliveryCost);
            UserAccountDTO userAccountDTO = userAccountService.updateAccountAmount(userId, cost, TransactionTypeEnum.PAY);
            UserAccountFlowDTO userAccountFlowDTO = new UserAccountFlowDTO();
            userAccountFlowDTO.setUserId(userId);
            userAccountFlowDTO.setTransactionId(IdUtil.getSnowflake().nextIdStr());
            userAccountFlowDTO.setTransactionType(TransactionTypeEnum.PAY);
            userAccountFlowDTO.setDocumentId(sysEntryOrderCode);
            userAccountFlowDTO.setDocumentType(DocumentTypeEnum.PICK_UP_ORDER);
            userAccountFlowDTO.setExpenseType(ExpenseTypeEnum.PICK_UP_ORDER);
            userAccountFlowDTO.setAmount(cost);
            userAccountFlowDTO.setRemainingBalance(userAccountDTO.getTotalBalance());
            userAccountFlowService.saveAccountFlow(userAccountFlowDTO);

        } finally {
            distributedLocker.unlock(entryOrderEditLockKey);
        }

    }

    @Override
    public void downloadEntryOrderLineTemplate(HttpServletResponse response) {
        EasyExcelUtil.exportExcelTemplate(response,
                ENTRY_ORDER_LINE_TEMPLATE_NAME,
                EntryOrderLineExcelDTO.class);

    }

    @Override
    public List<EntryOrderLineImportResultVO> importEntryOrderLines(String userId, String sysSupplierId, MultipartFile orderLineExcel) {
        List<EntryOrderLineExcelDTO> orderLines = EasyExcelUtil.read(orderLineExcel,
                EntryOrderLineExcelDTO.class,
                new EntryOrderLineListener());
        if (CollUtil.isEmpty(orderLines)) {
            return Lists.newArrayListWithCapacity(0);
        }
        List<String> skus = QtStreamUtil.map(orderLines, EntryOrderLineExcelDTO::getSku);
        List<EntryOrderLineResultEntity> supplierSkuList = localProductSupplierService.queryUserSupplierSkuList(userId,
                sysSupplierId,
                skus);
        Map<String, EntryOrderLineResultEntity> skuMap = QtStreamUtil.toMap(supplierSkuList, EntryOrderLineResultEntity::getSku);

        return QtStreamUtil.map(orderLines,
                orderLine -> EntryOrderLineImportResultVO.convert(skuMap.get(orderLine.getSku()), orderLine));
    }

    @Override
    public boolean wmsInbound(String sysEntryOrderCode, boolean allConfirm) {
        PickUpGoodsOrderEntity pickUpGoodsOrderEntity = pickUpGoodsOrderService.queryBySysEntryOrderCode(sysEntryOrderCode);
        PickUpOrderStatusEnum beforeState = pickUpGoodsOrderEntity.getState();
        if (beforeState != PickUpOrderStatusEnum.IN_PRODUCTION
                && beforeState != PickUpOrderStatusEnum.IN_STORAGE && beforeState != PickUpOrderStatusEnum.IN_TRANSIT && beforeState != PickUpOrderStatusEnum.BE_IN_STORAGE) {
            log.error("入库确认时，提货单状态错误，不在生产中、运输中、入库中、已入库的状态，而是：{}，状态变更失败", beforeState.getDesc());
            return false;
        }
        return pickUpGoodsOrderService.changeState(sysEntryOrderCode, beforeState,
               allConfirm ? PickUpOrderStatusEnum.BE_IN_STORAGE : PickUpOrderStatusEnum.IN_STORAGE);
    }


    private MPJLambdaWrapper<PickUpGoodsOrderEntity> createEntryOrderListWrapper(PickUpOrderQueryParam orderQueryParam) {
        boolean customerRole = orderQueryParam.isCustomerRole();
        List<String> merchantUserIds = orderQueryParam.getMerchantUserIds();
        PickUpOrderStatusEnum state = IEnumConvert.valueOf(orderQueryParam.getState(), PickUpOrderStatusEnum.class);

        MPJLambdaWrapper<PickUpGoodsOrderEntity> wrapper = JoinWrappers.lambda(PickUpGoodsOrderEntity.class);

        MFunc<MybatisLabelFree.Builder<EntryOrderLineEntity>> orderLineCollection = map ->
                map.result(EntryOrderLineEntity::getSkuId)
                        .result(EntryOrderLineEntity::getSkuQuantity)
                        .result(LocalProductEntity::getSku, EntryOrderLineEntity::getSku);

        wrapper.selectAll(PickUpGoodsOrderEntity.class)
                .selectAs(UserEntity::getUserName, ProductStockResultEntity::getMerchantUserName)
                .selectCollection(PickUpGoodsOrderEntity::getOrderLines, orderLineCollection)

                .leftJoin(EntryOrderLineEntity.class, on ->
                        on.eq(EntryOrderLineEntity::getSysEntryOrderCode, PickUpGoodsOrderEntity::getSysEntryOrderCode))

                .leftJoin(LocalProductEntity.class, on ->
                        on.eq(LocalProductEntity::getSkuId, EntryOrderLineEntity::getSkuId))

                .leftJoin(UserEntity.class, on ->
                        on.eq(UserEntity::getUserId, PickUpGoodsOrderEntity::getUserId))

                .eq(customerRole, PickUpGoodsOrderEntity::getUserId, orderQueryParam.getUserId())
                .eq(Objects.nonNull(state), PickUpGoodsOrderEntity::getState, state)
                .in(!customerRole && CollUtil.isNotEmpty(merchantUserIds),
                        PickUpGoodsOrderEntity::getUserId, merchantUserIds)
                .orderByDesc(PickUpGoodsOrderEntity::getUpdateTime);

        return wrapper;
    }


    private MPJLambdaWrapper<PickUpGoodsOrderEntity> createEntryOrderDetailWrapper(String sysEntryOrderCode) {


        MPJLambdaWrapper<PickUpGoodsOrderEntity> wrapper = JoinWrappers.lambda(PickUpGoodsOrderEntity.class);

        MFunc<MybatisLabelFree.Builder<EntryOrderLineEntity>> orderLineCollection = map ->
                map.result(EntryOrderLineEntity::getSkuId)
                        .result(EntryOrderLineEntity::getSkuQuantity)
                        .result(LocalProductEntity::getSku, EntryOrderLineEntity::getSku)
                        .result(LocalProductEntity::getProductEnTitle, EntryOrderLineEntity::getProductEnTitle);

        wrapper.selectAll(PickUpGoodsOrderEntity.class)
                .selectCollection(PickUpGoodsOrderEntity::getOrderLines, orderLineCollection)

                .leftJoin(EntryOrderLineEntity.class, on ->
                        on.eq(EntryOrderLineEntity::getSysEntryOrderCode, PickUpGoodsOrderEntity::getSysEntryOrderCode))

                .leftJoin(LocalProductEntity.class, on ->
                        on.eq(LocalProductEntity::getSkuId, EntryOrderLineEntity::getSkuId))

                .leftJoin(UserEntity.class, on ->
                        on.eq(UserEntity::getUserId, PickUpGoodsOrderEntity::getUserId))

                .eq(PickUpGoodsOrderEntity::getSysEntryOrderCode, sysEntryOrderCode);

        return wrapper;
    }
}